
    TestCase
    (
        'es5.DefinePropertiesTestCase'
        
    ,   {
			testEnvironmentIsNative: function ()
			{
				assertTrue('No extensions are present', null == Function.prototype.implement);
			}
			
		,	testSealAndPrototype: function ()
			{
				
				var Class= new Function
				
				,	error
				
				
				assertTrue('Class.prototype is extensible', Object.isExtensible(Class.prototype));
				
				Class.prototype.property= true;
				assertTrue('Could delete property before sealing', delete Class.prototype.property);
				
				// add it back on
				Class.prototype.property= {};
				Class.prototype.setProperty= function (value)
				{
					this.property= value;
				};
				Object.seal(Class.prototype);
				assertFalse('Class.prototype is not extensible', Object.isExtensible(Class.prototype));
				
				try
				{
					Class.prototype.trait= function () {}
				}
				catch (thrown)
				{
					error= thrown;
					console.log(error);
				}
				
				assertInstanceOf('A type error was thrown trying to extend Class.prototype', TypeError, error);
				
				assertFalse('The property could not be deleted from the prototype', delete Class.prototype.property);
				
				error= null;
				
				
				try
				{
					Class.prototype.property= 'newvalue';
				}
				catch (thrown)
				{
					error= thrown;
				}
				
				assertNull('The property value can still be changed', error);
				
				var instance= new Class
				,	propertyValue= 'propertyValue';
				
				instance.setProperty(propertyValue);
				
				assertSame('The property value can be changed on instances', propertyValue, instance.property);
				/*
				 * This is true in earlier editions of JavaScript as well.
				 */
				assertTrue('The property can still be deleted from instances', delete instance.property);
				
				assertTrue('The instance no longer has the property', 'string' === typeof instance.property);
				
				error= null;
				
				try
				{
					instance.newProperty= 'newProperty';
				}
				catch (thrown)
				{
					console.log(thrown);
					error= thrown;
				}
				
				assertNull('New properties can be added to instances', error);
				
				
			}
			
		,	testSealAndInstances: function () 
			{
				Sealed.prototype= 
				{
					constructor: Sealed
				,	property: null
				,	getProperty: function ()
					{
						return this.property;
					}
				,	setProperty: function (value)
					{
						this.property= value;
					}
				}
				function Sealed (dontSeal)
				{
					if (!dontSeal)
						Object.seal(this);
				};
				
				Object.seal(Sealed.prototype);
				
				var instance= new Sealed
				,	value= 'value'
				,	typeError
				
				assertTrue('Can still delete configurable properties!', delete instance.setProperty);
				assertSame('But will resort to prototype value', Sealed.prototype.setProperty, instance.setProperty);
				
				try
				{
					instance.newProperty= true;
				}
				catch (thrown)
				{
					error= thrown;
					console.log(error);
				}
				
				assertInstanceOf('But new members cannot be added', TypeError, error);
			}
			
		,	testPropertyDescriptors: function ()
			{
					
					/**
					 * The default values of a propety descriptor
					 * are all true
					 */
				var descriptor=
					{
						enumerable: true
					,	writable: true
					,	configurable: true
					}
				
				
				
				
			}
			
		,	testSealAndPropertyDescriptors: function ()
			{
				Class.implement= function (traits)
				{
					Object.defineProperties(this.prototype, traits);
					//Object.seal(this.prototype);
					return this;
				};
				
				function Class (fielValue)
				{
					/*
					 * If we seal an object, we prevent property
					 * descriptors from changing, existing
					 * properties being removed, and additional
					 * properties being added. Unlike a frozen
					 * object, a sealed objects properties are
					 * editable.
					 * 
					 * 
					 */
					
					this.setField(fieldValue);
					Object.seal(this);
				};
				
				assertTrue('Class.prototype is extensible', Object.isExtensible(Class.prototype));
				
				Class.implement
				(
					{
						getField: 
						{
							writable: false
						,	enumerable: true
						,	configurable: false
						,	value: function ()
							{
								if (null == this.field)
									throw new Error ('Field is not set');
									
								return this.field
							}
						}	
						
					,	setField:
						{
							writable: false
						,	enumerable: true
						,	configurable: false
						,	value: function (value)
							{
								if (null != this.field)
									throw new Error('Field already set');
									
								if (null == value)
									throw new Error('Field value cannot be null');
								
								this.field= value;
							}
						}
						
					,	field: 
						{
							writable: true
						,	enumerable: false
						,	configurable: false
						,	value: null
						}
					}
				);
				
				//assertFalse('Class prototype is no longer extensible', Object.isExtensible(Class.prototype));
				
				var fieldValue= 'fieldValue'
				,	instance= new Class(fieldValue)
				instance.field= false;
				
				assertSame('The field value was retrieved', fieldValue, instance.getField());
				

			}
			
		,	testSimplePropertyDescriptorExample: function ()
			{
				
				
				var instance= {};
				Object.defineProperties
				(
					instance
					
				,	{
						property: 
						{
							value: true
						,	writable: false
						}
						
					,	accessor:
						{
							get: function ()
							{
								return 'value';
							}
						}
					}
				);
				
				instance.property= false;
				
				console.log(instance.accessor);
				
				instance.property= true;
				
				console.log(instance.accessor);

			}
			
		,	testInheritedPropertyDescriptors: function ()
			{
				
				Object.defineProperties
				(
					Parent
				
				,	{
						field:
						{
							get: function () 
							{
								return 'defaultValue';
							}
						}
					}
				);
				
				Object.seal(Parent.prototype);
				
				function Parent () {};
				
				var instance= new Parent;
				instance.field= 'newValue';
				
				console.log(instance.field);
				
				instance= Object.create(Parent.prototype);
				instance.field= 'newValue';
				
				console.log(instance.field);
				
				Parent.prototype.field= 'newDefaultValue';
				
				console.log(Parent.prototype.field);
				
			}
        }
    );
